package org.vectrics.common.dom;

/**
 * @author mmoore
 */
import org.apache.log4j.Logger;
import org.w3c.dom.Element;
import org.exolab.castor.mapping.Mapping;
import org.exolab.castor.xml.Marshaller;
import org.exolab.castor.xml.Unmarshaller;
import org.vectrics.SystemException;
import org.vectrics.VectricsException;
import java.io.InputStream;

import org.xml.sax.InputSource;


public class MarshalUtils {
	private transient static Logger log = Logger.getLogger(MarshalUtils.class);
	private Mapping mapping = null;
	static private MarshalUtils instance = null;
	
	public MarshalUtils() {
		instance = this;
	}

	public static MarshalUtils getInstance() {
		if (instance == null)
			throw new SystemException("MarshalUtils instance not instantiated - call the constructor");
		return(instance);
	}
	
	public void loadMapping(InputStream inputStream) {
		InputSource inputSource = new InputSource(inputStream);
		mapping = new Mapping();
		try {
			mapping.loadMapping(inputSource);
		}
		catch (Exception ex) {
			mapping = null;
			throw new SystemException("Exception reading mapping from file and setting", ex);
		}
	}

	
	public void loadMappingFromFile(String fileName) {
		mapping = new Mapping();
		try {
			mapping.loadMapping(fileName);
		}
		catch (Exception ex) {
			mapping = null;
			throw new SystemException("Exception reading mapping from file and setting", ex);
		}
	}
	
	
	public Object elementToObject(Element element, Class theClass) {
		Unmarshaller unmarshaller = new Unmarshaller(theClass);
		if (mapping != null) {
			try {
				unmarshaller.setMapping(mapping);
			}
			catch (Exception ex) {
				throw new SystemException("Exception setting mapping of unmarshaller", ex);
			}
		}
		Object object = null;
		try {
			object = unmarshaller.unmarshal(element);
		}
		catch (Exception ex) {
			log.error("Exception unmarshalling element", ex);
			throw new SystemException("Exception unmarshalling element", ex);
		}
		return(object);
	}
	
	public void objectToElement(Element parent, Object object) {
		objectToElement(parent, object, null);
	}
	
	public void objectToElement(Element parent, Object object, String nodeName) {
		if (object == null)
			throw new SystemException("objectToElement() - object is null");
		
		log.debug("make w3c document");
		
		Marshaller marshaller = new Marshaller(parent);
		try {
			if (nodeName != null)
				marshaller.setRootElement(nodeName);
			if (mapping != null) {
				try {
					marshaller.setMapping(mapping);
				}
				catch (Exception ex) {
					throw new VectricsException("Exception setting mapping of marshaller", ex);
				}
			}
			
			marshaller.marshal(object);
		}
		catch (Exception ex) {
			log.error("Exception while marshalling object.  Class = " + object.getClass().getName(), ex);
			throw new SystemException("Exception while marshalling object.  Class = " + object.getClass().getName(), ex);
		}
	}

	
	/**
	 * @return Returns the mapping.
	 */
	public Mapping getMapping() {
		return mapping;
	}

	/**
	 * @param mapping The mapping to set.
	 */
	public void setMapping(Mapping mapping) {
		this.mapping = mapping;
	}

}
